package com.zhangsr.zus.remoting.netty;

import com.zhangsr.zus.common.URL;
import com.zhangsr.zus.remoting.api.Channel;
import com.zhangsr.zus.remoting.api.ChannelHandler;
import com.zhangsr.zus.remoting.api.Server;
import com.zhangsr.zus.remoting.api.exception.RemotingException;
import com.zhangsr.zus.remoting.api.transport.AbstractServer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;
import org.apache.log4j.Logger;

import java.net.InetSocketAddress;
import java.util.Collection;

/**
 * @Author: zhangsr
 */
public class NettyServer extends AbstractServer implements Server {

    private static Logger logger = Logger.getLogger(NettyServer.class);

    public NettyServer(URL url, ChannelHandler handler) throws RemotingException {
        super(url, handler);
    }

    private static final int BIZ_GROUP_SIZE = Runtime.getRuntime().availableProcessors() * 2;
    private static final int BIZ_THREAD_SIZE = 4;

    @Override
    protected void doOpen() throws Throwable {

        logger.info("start netty server ...");
        // Server 服务启动
        final EventLoopGroup boosGroup = new NioEventLoopGroup(BIZ_GROUP_SIZE);
        final EventLoopGroup workerGroup = new NioEventLoopGroup(BIZ_THREAD_SIZE);

        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(boosGroup, workerGroup);
        bootstrap.channel(NioServerSocketChannel.class);
        final NettyHandler nettyHandler = new NettyHandler(getUrl(), this);
        bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel socketChannel) throws Exception {
                NettyCodecAdapter adapter = new NettyCodecAdapter(getCodec(), getUrl(), NettyServer.this);

                ChannelPipeline pipeline = socketChannel.pipeline();
                pipeline.addLast("decoder", adapter.getDecoder());
                pipeline.addLast("encoder", adapter.getEncoder());
                pipeline.addLast("handler", nettyHandler);
            }
        });

        // 绑定接口，同步等待成功
        bootstrap.bind(getBindAddress()).sync();

        logger.info("start netty server end.");
    }

    @Override
    protected void doClose() throws Throwable {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    public Collection<Channel> getChannels() {
        return null;
    }

    public Channel getChannel(InetSocketAddress remoteAddress) {
        return null;
    }
}
